/*
 * GeoVISTA Center (Penn State, Dept. of Geography)
 * Copyright (c), 2003-2011,  Jin Chen and Alan M. MacEachren, GeoVISTA Center, Penn State University
 * All Rights Researved.
 *
 * This library is developed and distributed for free usage,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * You can redistribute and/or modify it under the terms of the
 * Simplified BSD License
 *
 *
 *
 *
 *
 *
 *
 *  
 * @Original Author: jin Chen
 * @date: Apr 2, 2004$
 * @version: 1.0
 */
package edu.psu.geovista.app.dataloader.v1.xml;

import edu.psu.geovista.app.dataloader.v1.config.auto.*;
import edu.psu.geovista.app.dataloader.v1.config.auto.Collection;
import edu.psu.geovista.app.dataloader.v1.config.auto.impl.AttributeImpl;
import edu.psu.geovista.app.dataloader.v1.config.auto.impl.CollectionImpl;
import edu.psu.geovista.app.dataloader.v1.config.auto.impl.CollectionTypeImpl;
import edu.psu.geovista.common.utils.TimeUtils;
import org.apache.commons.beanutils.BeanUtils;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.*;

public class JaxbPathsXMLFs implements PathsXMLFileSystem {
    /*public static String MODEL_ROOT="";
    final public static String RESOURCES="resources/";
    public static String XMLs="";*/
    File file;

    JAXBContext jc ;
    ObjectFactory obfty;
    Collection root;
    List projectList;
    //Project template;

    public JaxbPathsXMLFs() {
          // this.configFile=configFile;
          // load();
    }

    public void load(){
       // this.file=file;
        try {
            obfty=new ObjectFactory();
            jc = JAXBContext.newInstance("edu.psu.geovista.app.pcp.dataloader.config.auto"); //edu.psu.geovista.app.pcp.dataloader.config.auto
            Unmarshaller unmarshaller = jc.createUnmarshaller();
            unmarshaller.setValidating(true);

            if (this.file.exists() ) {
                root= (Collection) unmarshaller.unmarshal(this.file);
                //1. get document
                CollectionType.ProjectsType projectTypes=root.getProjects();

                projectList=projectTypes.getProject();

            } else { //create a empty collection

               root=getRootInstance();
               CollectionType.ProjectsType projectTypes=root.getProjects();
               projectList=projectTypes.getProject();

            }
        } catch (JAXBException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
    }


    /*******************************************************************************************************
     *                service
     *******************************************************************************************************/
      /**************************************************
      *                add project
      ***************************************************/
   public void add(Project proj){
         this.projectList.add(proj);
     }

    public void setProject(edu.psu.geovista.app.dataloader.v1.config.model.Project proj) {
       // DataConvertor.
        //need convert to xmlproj

        this.projectList.add(proj);
    }

    /**************************************************
     *                save
     ***************************************************/
    public void save() throws FileNotFoundException {
        FileOutputStream out=new FileOutputStream(file);
        print(jc,root,out);
    }
    /**************************************************
     *                new instance; colone
     ***************************************************/
    /**
     *
     * @return  a tree structure starting from root, with all element initiated (no null leaf node)
     */
    public  static Collection getRootInstance(){
        Collection root=new CollectionImpl();
        CollectionType.ProjectsType projectTypes=new CollectionTypeImpl.ProjectsTypeImpl();
        root.setProjects(projectTypes);
        List projectlist=projectTypes.getProject() ;

        return root;
    }
    /**************************************************
     *                get project infos
     ***************************************************/
    public edu.psu.geovista.app.dataloader.v1.config.model.Project getProjectByIDIngoreCase(String id){
        edu.psu.geovista.app.dataloader.v1.config.auto.Project xmlproj = this.getXMLProjectByIDIngoreCase(id);
        edu.psu.geovista.app.dataloader.v1.config.model.Project appProj = JaxbPathInfoConvertor.convert(xmlproj);
        return appProj;
     }
     public edu.psu.geovista.app.dataloader.v1.config.model.Project getProjectByID(String id){
         Project xmlproj = getXMLProjectByID(id);
         edu.psu.geovista.app.dataloader.v1.config.model.Project appProj = JaxbPathInfoConvertor.convert(xmlproj);
         return appProj;
     }

    public List getSortedProjectIDs(){
       List ids=new ArrayList();
       Iterator iter=projectList.iterator() ;
       while(iter.hasNext()){
          Project project= (Project)iter.next();
          ids.add(project.getID() );
       }
       return ids;
    }

    //add projects
    public void setProjectIDs(String[] ids ){
        projectList.clear() ;
        for (int i=0;i<ids.length ;i++){
            Project proj=null;//ModelUtils.getProjectInstance();
            try {
                proj = obfty.createProject();
                proj.setID(ids[i]);
                projectList.add(proj);
            } catch (JAXBException e) {
                e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
            }

        }
    }

    protected  Project getXMLProjectByID(String id){
       for (int i=0;i<projectList.size() ;i++){
            Project project=(Project) projectList.get(i);
            if(id.equals(project.getID())){
                return project;
            }
        }
        return null;
    }

     protected  Project getXMLProjectByIDIngoreCase(String id){
        for (int i=0;i<projectList.size() ;i++){
            Project project=(Project) projectList.get(i);
            if(id.equalsIgnoreCase(project.getID())){
                return project;
            }
        }
        return null;
    }
    /**
     *  
     * @return
     */
    public List getSortProjectList(){
        class ProjectComparator implements Comparator{
            public int compare(Object o1, Object o2) {
                Project p1=(Project) o1;
                Project p2=(Project) o2;
                Date date1=TimeUtils.convertStringToDate(p1.getTime()) ;
                Date date2=TimeUtils.convertStringToDate(p2.getTime()) ;
                if(date1.before(date2) ){
                    return 1;
                }
                else if(date1.after(date2) ) {
                    return -1;
                }
                else{
                    return 0;  //To change body of implemented methods use File | Settings | File Templates.
                }
            }

        }
        //this.projectList;
        Collections.sort(projectList,new ProjectComparator() );

        return projectList;
    }

    public File getFile() {
        return file;
    }

    public void setFile(File file) {
        this.file = file;
    }

    /*******************************************************************************************************
     *                 Only for testing purposes
     *******************************************************************************************************/
    public void print() {
        print(jc,root,System.out);
    }
    public static void testRead() {
        try {
            JAXBContext jc = JAXBContext.newInstance("edu.psu.geovista.app.pcp.dataloader.config.auto");
            Unmarshaller unmarshaller = jc.createUnmarshaller();
            unmarshaller.setValidating(true);

            Collection collection= (Collection)
            unmarshaller.unmarshal(new File( "Project.xml"));

            CollectionType.ProjectsType projectTypes=collection.getProjects();
            List projList=projectTypes.getProject();
            for (int i=0;i<projList.size() ;i++){
                Project project=(Project) projList.get(i);
                try {
                    Map map = BeanUtils.describe(project);
                    //BeanUtils.

                } catch (IllegalAccessException e) {
                    e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                } catch (InvocationTargetException e) {
                    e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                }


                //update
                Pcpdata pcpdata=project.getPcpdata() ;
                Attributes attrs=pcpdata.getSelectedAttributes() ;
                List attlist=attrs.getAttr();
                attlist.clear();
                attlist.add(getAttr("change1"));
                attlist.add(getAttr("change2"));


            }

         print(jc,collection,System.out);
        } catch (JAXBException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
    }

    private static Attribute getAttr(String name){
         AttributeImpl att=new AttributeImpl();
         att.setName(name);
         return att;

    }

    private static void print(JAXBContext jc, Collection coll,OutputStream output){
        try {



            Marshaller m=jc.createMarshaller();
            m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE ) ;
            m.marshal(coll,output);
        } catch (JAXBException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }

    }
    public static void main(String[] args) {
           testRead();
    }
}

   /* public static void clone(ProjectType from, ProjectType to){
         PcpdataType pcpdata=from.getPcpdata();
         TsdataType tsdata=from.getTsdata() ;
    }*/
    /*// 
    public static ProjectType cloneProject(ProjectType frm) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
            return (ProjectType) BeanUtils.cloneBean(frm);
    }*/
    /*******************************************************************************************************
     *                project id
     *******************************************************************************************************/
    //public static String[] getSortedProjectIDs(List projectList) {
         //return CollectionUtils.convertToStringArray(this.)
        /*int len=projectList.size();
        if(len<=0) return new String[0];
        String[] ids=new String[len];
        for (int i=0;i<len ;i++){
            ProjectType project=(ProjectType) projectList.get(i);
            ids[i]=project.getID();
        }
        return ids;*/

        //wrong:return CollectionUtils.convertToStringArray(this.getSortProjectList());
    //}
  /**************************************************
      *                add project
      ***************************************************/
   /*  public void add(Project proj){
         this.projectList.add(proj);
     }*/


// 
   /* private static TvImpl getTvtypeImplByName(Tvs timevalue,String name) {

    List list=timevalue.getTimevalue() ;
    for (int i=0;i<list.size() ;i++){
         TvImpl tv =(TvImpl) list.get(i);
         if(tv.getAttrName().equals(name) ){
             return tv;
         }
    }
    return null;
}*/
